op {
  graph_op_name: "Fingerprint"
  endpoint {
    name: "Fingerprint"
  }
  in_arg {
    name: "data"
    description: <<END
Must have rank 1 or higher.
END
  }
  in_arg {
    name: "method"
    description: <<END
Fingerprint method used by this op. Currently available method is
`farmhash::fingerprint64`.
END
  }
  out_arg {
    name: "fingerprint"
    description: <<END
A two-dimensional `Tensor` of type `tf.uint8`. The first dimension equals to
`data`'s first dimension, and the second dimension size depends on the
fingerprint algorithm.
END
  }
  attr {
    name: "T"
    description: <<END
This can be a POD-type or string type.
END
  }
  summary: "Generates fingerprint values."
  description: <<END
Generates fingerprint values of `data`.

Fingerprint op considers the first dimension of `data` as the batch dimension,
and `output[i]` contains the fingerprint value generated from contents in
`data[i, ...]` for all `i`.

Fingerprint op writes fingerprint values as byte arrays. For example, the
default method `farmhash64` generates a 64-bit fingerprint value at a time.
This 8-byte value is written out as an `uint8` array of size 8, in little-endian
order.

For example, suppose that `data` has data type `DT_INT32` and shape (2, 3, 4),
and that the fingerprint method is `farmhash64`. In this case, the output shape
is (2, 8), where 2 is the batch dimension size of `data`, and 8 is the size of
each fingerprint value in bytes. `output[0, :]` is generated from 12 integers in
`data[0, :, :]` and similarly `output[1, :]` is generated from other 12 integers
in `data[1, :, :]`.

Note that this op fingerprints the raw underlying buffer, and it does not
fingerprint Tensor's metadata such as data type and/or shape. For example, the
fingerprint values are invariant under reshapes and bitcasts as long as the
batch dimension remain the same:

```
Fingerprint(data) == Fingerprint(Reshape(data, ...))
Fingerprint(data) == Fingerprint(Bitcast(data, ...))
```

For string data, one should expect `Fingerprint(data) !=
Fingerprint(ReduceJoin(data))` in general.
END
}
